import socket
import time

# 数据通信格式：
# 字节序：小端字节序
# 包格式：包头+包长+包ID+数据+包尾
# 包头："PACKET_START"
# 包长：8字节无符号整数（字节数，包含[包类型 + 数据 + 包尾]）
# 包类型：4字节char
# 数据：任意字节
# 包尾："PACKET_END"


# //Socket连接参数
# #define NET_TCP_PORT             8888    //TCP服务器监听“起始”端口号
# #define NET_PORT_SPACE           10      //尝试监听、绑定、广播端口号间隔
#
# #define NET_SOCKET_TIMEOUT       10*1000 //多长时间没有收到客户端信息说明已经断开
# #define NET_SHAKE_HAND_ENABLED   false
#
# //包数据结构 : [ 包头 + 长度(8字节) + 包类型(4字节) + 数据 + 包尾 ]
# #define NET_PACKET_START                "PACKET_START"
# #define NET_PACKET_END                  "PACKET_END"
# #define NET_PACKET_TYPE_BYTES           4    //包类型占几个字节
# #define NET_PACKET_LTNGTH_BYTES         8    //包数据长度占几个字节
#
#  //包类型
# #define NET_PACKET_TYPE_CMD                 "0001" //命令
# #define NET_PACKET_TYPE_LOG				  "0002" //日志
# #define NET_PACKET_TYPE_IMAGE               "0003" //图像
# #define NET_PACKET_TYPE_SYSTEM_STATUS       "0004" //系统状态
#
# //命令枚举（即发送命令时具体填入的数据）
# // 客户端命令
# #define REQUEST_OPEN_CAMERA              "OPEN_CAMERA" //打开相机
# #define REQUEST_CLOSE_CAMERA             "CLOSE_CAMERA" //关闭相机
# #define REQUEST_TAKE_PHOTO               "TAKE_PHOTO" //拍照
# // 服务端回复命令
# #define RESPONSE_CAMERA_OPEN_SUCCESS            "CAMERA_OPEN_SUCCESS" //相机打开成功
# #define RESPONSE_CAMERA_OPEN_FAILED             "CAMERA_OPEN_FAILED" //相机打开失败
# #define RESPONSE_CAMERA_CLOSE_SUCCESS           "CAMERA_CLOSE_SUCCESS" //相机关闭成功
# #define RESPONSE_CAMERA_CLOSE_FAILED            "CAMERA_CLOSE_FAILED" //相机关闭失败
# #define RESPONSE_PHOTO_TAKEN_SUCCESS            "PHOTO_TAKEN_SUCCESS" //照片拍摄成功
# #define RESPONSE_PHOTO_TAKEN_FAILED             "PHOTO_TAKEN_FAILED" //照片拍摄失败

class SocketServer:
    host = '127.0.0.1'
    port = 8888
    packet_start = b"PACKET_START"
    packet_end = b"PACKET_END"
    packet_type_bytes = 4
    packet_length_bytes = 8
    
    server_socket = None
    client_socket = None
    client_address = None
    # 接收缓存
    dataBuffer = bytes()
    #收包回调函数字典
    recv_callback_dict = {}
    def __init__(self, host='127.0.0.1', port=8888):
        self.host = host
        self.port = port
        self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 注册收包回调函数
    def register_recv_callback(self, pack_type, callback):
        # self.recv_callback_dict[pack_type] = callback
        self.recv_callback_dict.update({pack_type: callback})

    def send_data(self, pack_type, pack_data):
        send_buff = bytes()
        send_buff += self.packet_start
        # 计算包长
        pack_len = self.packet_type_bytes + pack_data.__len__() + self.packet_end.__len__()

        #将数字转为字符串不足的填0
        pack_len_byte = str(pack_len).zfill(self.packet_length_bytes).encode('utf-8')
        send_buff += pack_len_byte
        # 写入包长
        send_buff += pack_type
        send_buff += pack_data
        send_buff += self.packet_end
        try:
            self.client_socket.sendall(send_buff)
        except socket.error as e:
            print(f"发送数据时发生 socket 错误：{e}")
        except ValueError as e:
            print(f"发送数据时发生值错误：{e}")

    def start(self):
        # 绑定并监听
        self.server_socket.bind((self.host, self.port))
        self.server_socket.listen()
        print(f"服务器在 {self.host}:{self.port} 启动，等待连接...")

        while True:
            # 接受客户端连接
            self.client_socket, self.client_address = self.server_socket.accept()
            with self.client_socket:
                print(f"连接来自 {self.client_address}")
                self.handle_client(self.client_socket)

    def handle_client(self, client_socket):
        # 新建一个线程接收客户端消息
        while True:
            # 接收数据
            try:
                buffer = self.client_socket.recv(1024)
                if not buffer:
                    break  # 如果没有数据，则退出循环

                self.dataBuffer = self.dataBuffer + buffer
                self.unpack_data()
            except Exception as e:
                print(f"接收数据时发生错误: {e}")
                break  # 如果发生异常，则退出循环
        self.wait_for_reconnect()  # 等待重新连接

    def wait_for_reconnect(self):
        print("等待重新连接...")
        while True:
            try:
                # 继续接受新的客户端连接
                self.client_socket, self.client_address = self.server_socket.accept()
                print(f"连接来自 {self.client_address}")
                self.handle_client(self.client_socket)  # 新线程或方法处理这个连接
                break  # 成功连接后跳出循环
            except Exception as e:
                print(f"连接失败，错误: {e}")
                # 可以选择等待一段时间再重试
                time.sleep(3)  # 等待3秒后继续尝试连接

    def stop(self):
        self.server_socket.close()
        print("服务器已停止")

    # 解包函数
    def unpack_data(self):
        if self.dataBuffer.__len__() < self.packet_start.__len__():
            return  # 缓冲区不够长，继续等待
        
        # 找到包头
        start_index = self.dataBuffer.find(self.packet_start)
        if start_index == -1:
            # 清除除了最后的包头长度外的缓冲区
            self.dataBuffer = self.dataBuffer[self.dataBuffer.__len__() - self.packet_start.__len__():]
            return  # 未找到包头，继续等待

        # 确保缓冲区足够长
        if start_index + self.packet_start.__len__() + self.packet_length_bytes > len(self.dataBuffer):
            return  # 缓冲区不够长，继续等待

        # 找到包头后，确定包长
        pack_len_byte = self.dataBuffer[(start_index + self.packet_start.__len__()):(start_index + self.packet_start.__len__() + self.packet_length_bytes)]
        pack_len = pack_len = int(pack_len_byte.decode('utf-8'))
        if (start_index + self.packet_start.__len__() + pack_len) > len(self.dataBuffer):
            return  # 缓冲区不够长，继续等待

        # 判断包尾
        end_index = start_index + self.packet_start.__len__() + self.packet_length_bytes + pack_len - self.packet_end.__len__()
        if self.dataBuffer[end_index:end_index + self.packet_end.__len__()] != self.packet_end:
            print("包尾不正确")
            return  # 包尾不正确，继续等待
        # 找到包尾后，分割包类型和数据
        pack_type = self.dataBuffer[(start_index + self.packet_start.__len__() + self.packet_length_bytes):(start_index + self.packet_start.__len__() + self.packet_length_bytes + self.packet_type_bytes)]
        pack_data = self.dataBuffer[(start_index + self.packet_start.__len__() + self.packet_length_bytes + self.packet_type_bytes):(start_index + self.packet_start.__len__() + self.packet_length_bytes + pack_len - self.packet_end.__len__())]
        # 调用回调函数
        if pack_type in self.recv_callback_dict:
            self.recv_callback_dict[pack_type](pack_data)
        else:
            print(f"未注册的包ID：{pack_type}")

        # 处理剩余缓冲区
        self.dataBuffer = self.dataBuffer[(start_index + self.packet_start.__len__() + self.packet_length_bytes + pack_len):]

        # 读取包长


        # length = len(buffer)
        # if length > 9:
        #     pack_type = int.from_bytes(buffer[2:6], byteorder='little', signed=False)
        #     pack_len = int.from_bytes(buffer[6:10], byteorder='little', signed=False)
        #     if length > 10:
        #         pack_data = buffer[10:pack_len]
        #     else:
        #         pack_data = None
        #         self.recv_callback_dict[pack_type](pack_data)
        #     else:
        #         print(f"未注册的包ID：{pack_type}")


if __name__ == "__main__":
    server = SocketServer()
    try:
        server.start()
    except KeyboardInterrupt:
        server.stop()
